<script setup lang="ts">
import { computed, ref, shallowRef, watch } from 'vue';
import { NTag } from 'naive-ui';
import { $t } from '@/locales';
import type { MenuTree, Role } from '@/service/api';
import {
  assignRoleMenu,
  fetchGetAllPages,
  fetchGetSimpleMenuTree,
  fetchHomePageByRoleId,
  fetchMenuIdListByRoleId,
  updateHomePageByRoleId
} from '@/service/api';

defineOptions({
  name: 'MenuAuthModal'
});

type RoleModel = Pick<Role, 'id' | 'name' | 'code' | 'remark'>;
interface Props {
  /** the role */
  role: RoleModel;
}

const props = defineProps<Props>();

const visible = defineModel<boolean>('visible', {
  default: false
});

function closeModal() {
  visible.value = false;
}

const title = computed(() => $t('common.edit') + $t('page.manage.role.menuAuth'));

const home = ref('');

async function getHome() {
  home.value = '';
  const { data } = await fetchHomePageByRoleId(props.role.id);

  home.value = data !== null ? data : '';
}

async function updateHome(val: string) {
  // request
  const { error } = await updateHomePageByRoleId(props.role.id, val);
  if (error) {
    home.value = '';
    window.$message?.success($t('page.manage.role.roleHomePageUpdateFail'));
  } else {
    home.value = val;
    window.$message?.success($t('page.manage.role.roleHomePageUpdateSuccess'));
  }
}

const pages = shallowRef<string[]>([]);

async function getPages() {
  const { error, data } = await fetchGetAllPages();

  if (!error) {
    pages.value = data;
  }
}

const pageSelectOptions = computed(() => {
  const opts: CommonType.Option[] = pages.value.map(page => ({
    label: page,
    value: page
  }));

  return opts;
});

const tree = shallowRef<MenuTree[]>([]);

async function getTree() {
  const { error, data } = await fetchGetSimpleMenuTree();

  if (!error) {
    tree.value = data;
  }
}

const checks = ref<number[]>([]);

async function getChecks() {
  checks.value = [];
  const { data } = await fetchMenuIdListByRoleId(props.role.id);

  checks.value = data !== null ? data : [];
}

const treeNodeAll = ref(false); // 全选/全不选

/** 全选/全不选 */
const handleCheckedTreeNodeAll = () => {
  // checks.value = treeNodeAll.value ? tree.value.map(item => item.id) : [];
  checks.value = treeNodeAll.value ? getTreeAllIds(tree.value, checks.value) : [];
};

function getTreeAllIds(treeData: MenuTree[], checksNode: number[]) {
  if (!Array.isArray(treeData)) return []; // 如果不是一个数组，则返回

  treeData.forEach(node => {
    checksNode.push(node.id);
    if (node.children && node.children.length > 0) {
      // 递归调用getAllIds处理子节点
      getTreeAllIds(node.children, checksNode);
    }
  });
  return checksNode;
}

const treeExpandAll = ref(false); // 全部展开/折叠

async function handleSubmit() {
  // request
  const { error } = await assignRoleMenu(props.role.id, checks.value);

  if (!error) {
    window.$message?.success?.($t('common.modifySuccess'));
    closeModal();
  }
}

function init() {
  getHome();
  getPages();
  getTree();
  getChecks();
  treeNodeAll.value = false;
  treeExpandAll.value = false;
}

watch(visible, val => {
  if (val) {
    init();
  }
});
</script>

<template>
  <NModal v-model:show="visible" :title="title" preset="card" class="w-280">
    <NForm label-placement="left" label-align="right" label-width="80px">
      <NFormItem :label="$t('page.manage.role.roleName')">
        <NTag type="info">{{ role.name }}</NTag>
      </NFormItem>
      <NFormItem :label="$t('page.manage.role.roleCode')">
        <NTag type="info">{{ role.code }}</NTag>
      </NFormItem>
      <NFormItem :label="$t('page.manage.menu.home')">
        <NSelect :value="home" :options="pageSelectOptions" size="small" class="w-160px" @update:value="updateHome" />
      </NFormItem>
      <NFormItem :label="$t('page.manage.role.menuAuth')">
        <NCard
          class="shadow-lg"
          :hoverable="true"
          header-style="font-size: 14px; padding: 8px; border-bottom: 1px solid #e5e7eb"
        >
          <template #header>
            {{ $t('common.checkAllOrUncheckAll.checkAllOrUncheckAll') }}
            <NSwitch v-model:value="treeNodeAll" @update:value="handleCheckedTreeNodeAll">
              <template #checked>{{ $t('common.yesOrNo.yes') }}</template>
              <template #unchecked>{{ $t('common.yesOrNo.no') }}</template>
            </NSwitch>
            &nbsp; &nbsp; {{ $t('common.expandAllOrCollapsedAll.expandAllOrCollapsedAll') }}
            <NSwitch v-model:value="treeExpandAll">
              <template #checked>{{ $t('common.expandAllOrCollapsedAll.expandAll') }}</template>
              <template #unchecked>{{ $t('common.expandAllOrCollapsedAll.collapsedAll') }}</template>
            </NSwitch>
          </template>

          <!-- cascade -->
          <NTree
            v-model:checked-keys="checks"
            allow-checking-not-loaded
            :data="tree"
            key-field="id"
            :default-expand-all="treeExpandAll"
            checkable
            expand-on-click
            virtual-scroll
            block-line
            class="m-t h-100"
          />
        </NCard>
      </NFormItem>
    </NForm>
    <template #footer>
      <NSpace justify="end">
        <NButton size="small" class="mt-16px" @click="closeModal">
          {{ $t('common.cancel') }}
        </NButton>
        <NButton type="primary" size="small" class="mt-16px" @click="handleSubmit">
          {{ $t('common.confirm') }}
        </NButton>
      </NSpace>
    </template>
  </NModal>
</template>

<style scoped></style>
